﻿

namespace KingerRobot.CambodiaSailunMDC.SpiService.Managers;
public class TaskManager
{
    protected readonly Db m_Db;


    public TaskManager(Db db = null)
    {
        this.m_Db = db ?? Db.Default;
    }

    #region 公共

    public int SaveChanges()
    {
        return this.m_Db.SaveChanges();
    }

    /// <summary>
    /// 根据任务Id获取任务和指令
    /// </summary>
    public TaskAndCmd GetTaskAndCmdByTaskId(long taskId)
    {
        var task = this.m_Db.WcsTasks.FirstOrDefault(t => t.UseFlag == 1 && t.Id == taskId);
        if (task != null)
        {
            var taskCmd = this.m_Db.WcsTaskCmds.OrderByDescending(item => item.CreateTime).FirstOrDefault(t => t.UseFlag == 1 && t.TaskId == taskId);
            if (taskCmd != null)
            {
                return new TaskAndCmd() { Task = task, TaskCmd = taskCmd };
            }
            WriteLog($"未找到任务Id为{taskId}的指令", true);
        }
        return null;
    }

    /// <summary>
    /// 设置堆垛机任务类型
    /// </summary>
    /// <param name="forkId"></param>
    /// <param name="taskType"></param>
    public void SetCrnType(long? forkId,int taskType)
    {
        var crn = this.m_Db.RcsEquipCrns.Where(f => f.CrnFork1 == forkId || f.CrnFork2 == forkId).FirstOrDefault();

        if(crn is not null)
        {
            crn.NowTaskType = taskType;
        }
    }

    /// <summary>
    /// 根据任务号获取任务和指令
    /// </summary>
    public TaskAndCmd GetTaskAndCmdByTaskNo(int taskNo)
    {
        var task = this.m_Db.WcsTasks.FirstOrDefault(t => t.UseFlag == 1 && t.TaskNo == taskNo);
        if (task != null)
        {
            var taskCmd = this.m_Db.WcsTaskCmds.OrderByDescending(item => item.CreateTime).FirstOrDefault(t => t.UseFlag == 1 && t.TaskNo == taskNo);
            if (taskCmd != null)
            {
                return new TaskAndCmd() { Task = task, TaskCmd = taskCmd };
            }
            WriteLog($"未找到任务号为{taskNo}的指令", true);
        }
        return null;
    }

    ///// <summary>
    ///// 获取当前排的EMS可执行任务数量
    ///// </summary>
    //public int GetDitchExcutableEmsTaskCount(long ditch)
    //{
    //    return this.m_Db.WcsTasks.Count(f => f.CuringDitch == ditch && f.TaskType == (int)EnumTaskType.EMS && f.TaskStatus == (int)EnumTaskStatus.Executable);
    //}

    ///// <summary>
    ///// 制作回写list
    ///// </summary>
    ///// <param name="endParams"></param>
    ///// <param name="curingTireId"></param>
    ///// <param name="compFlage">完毕标识 S-堆垛机出库完成，E-EMS完成</param>
    //public void CreateEndParams(ref List<EndParam> endParams,long? curingTireId,string compFlage)
    //{
    //    var inCuringTire = this.m_Db.WcsInCuringTires.Where(f => f.Id == curingTireId).FirstOrDefault();

    //    if(inCuringTire is null)
    //    {
    //        return;
    //    }

    //    endParams.Add(new EndParam()
    //    {
    //        TcmNo = inCuringTire.CuringCode,
    //        TcmDir = inCuringTire.CuringDir,
    //        TirCode = inCuringTire.TireCode,
    //        TcmSpec = inCuringTire.CuringSpec,
    //        TcmSpecDesc = inCuringTire.CuringSpecDesc,
    //        CompFlag = compFlage,
    //        TbmPs = inCuringTire.TbmPs,
    //        Angle = inCuringTire.RotateAngle,
    //    });
    //}

    /// <summary>
    /// 根据开始位置和状态获取任务和指令
    /// </summary>
    public TaskAndCmd GetTaskAndCmdByStartLocAndStatus(long startLoc, EnumTaskStatus status)
    {
        var taskCmd = this.m_Db.WcsTaskCmds.FirstOrDefault(t => t.UseFlag == 1 && t.StartLoc == startLoc && t.CmdStatus == (int)status);
        if (taskCmd != null)
        {
            var task = this.m_Db.WcsTasks.FirstOrDefault(t => t.UseFlag == 1 && t.Id == taskCmd.TaskId);
            if (task != null)
            {
                return new TaskAndCmd() { Task = task, TaskCmd = taskCmd };
            }
            WriteLog($"GetTaskAndCmdByStartLocAndStatus：未找到任务号为{taskCmd.TaskId}的指令", true);
        }
        return null;
    }

    /// <summary>
    /// 根据开始位置获取可以执行的指令
    /// </summary>
    public POWcsTaskCmd GetExecutableTaskCmdByLocId(long locId)
    {
        return this.m_Db.WcsTaskCmds.FirstOrDefault(t => t.CmdStatus < (int)EnumTaskCmdStatus.Executed && t.StartLoc == locId);
    }

    /// <summary>
    /// 添加异常任务和指令
    /// </summary>
    public TaskAndCmd AddAbnormalTaskAndCmd(long? skuId, string tireCode, long startLoc, string remark, POWcsNetAbnormal abnormalPath = null,int taskNo = 0)
    {
        if (abnormalPath == null)
        {
            abnormalPath = PathHelper.GetAbnormalPath(startLoc);
        }

        var task = this.AddTask(skuId, tireCode, EnumTaskType.Abnormal, startLoc, abnormalPath.TargetLoc.Value, remark,0,0,null,taskNo);
        var taskCmd = this.AddAbnormalTaskCmd(task, startLoc, remark, abnormalPath);
        return new TaskAndCmd()
        {
            Task = task,
            TaskCmd = taskCmd
        };
    }

    public TaskAndCmd AddAbnormalTaskAndCmdWithTargetLoc(long? skuId, string tireCode, long startLoc, string remark, long targetLoc, int taskNo = 0)
    {

        var task = this.AddTask(skuId, tireCode, EnumTaskType.Abnormal, startLoc, targetLoc, remark,0,0,null,taskNo);
        var taskCmd = this.AddTaskCmd(task, startLoc, targetLoc, remark);
        return new TaskAndCmd()
        {
            Task = task,
            TaskCmd = taskCmd
        };
    }

    /// <summary>
    /// 添加异常任务和指令
    /// </summary>
    public TaskAndCmd EditorTaskAndCmdToAbnormal(TaskAndCmd taskAndCmd, long startLoc, string remark, POWcsNetAbnormal abnormalPath = null)
    {
        if (abnormalPath == null)
        {
            abnormalPath = PathHelper.GetAbnormalPath(startLoc);
        }

        BakAndDeleteCmd(taskAndCmd.TaskCmd);

        var task = taskAndCmd.Task;

        task.TaskType = (int)EnumTaskType.Abnormal;
        task.TaskStatus = (int)EnumTaskStatus.Executable;
        task.IsAbnormal = true;
        task.TargetLoc = abnormalPath.TargetLoc;
        task.RemarkMemo = remark;

        var taskCmd = this.AddAbnormalTaskCmd(task, startLoc, remark, abnormalPath);

        return new TaskAndCmd()
        {
            Task = task,
            TaskCmd = taskCmd
        };
    }


    /// <summary>
    /// 添加异常指令
    /// </summary>
    public POWcsTaskCmd AddAbnormalTaskCmd(POWcsTask task, long startLoc, string remark, POWcsNetAbnormal abnormalPath = null)
    {
        if (abnormalPath == null)
        {
            abnormalPath = PathHelper.GetAbnormalPath(startLoc);
        }
        long taskCmdTargetLoc = abnormalPath.TargetLoc.Value;
        if (abnormalPath.CacheLoc.HasValue)
        {
            taskCmdTargetLoc = abnormalPath.CacheLoc.Value;
        }
        return this.AddTaskCmd(task, startLoc, taskCmdTargetLoc, remark);
    }

    /// <summary>
    /// 添加任务和指令
    /// </summary>
    public TaskAndCmd AddTaskAndCmd(long? trackId, string tireCode, EnumTaskType taskType, long startLoc, long taskTargetLoc, long taskCmdTargetLoc, string remark,long? equipId = 0, long? productId = 0,string toolTip = null)
    {
        var task = this.AddTask(trackId, tireCode, taskType, startLoc, taskTargetLoc, remark,equipId,productId,toolTip);
        var taskCmd = this.AddTaskCmd(task, startLoc, taskCmdTargetLoc, remark);

        return new TaskAndCmd()
        {
            Task = task,
            TaskCmd = taskCmd
        };
    }

    /// <summary>
    /// 添加任务
    /// </summary>
    public POWcsTask AddTask(long? trackId, string tireCode, EnumTaskType taskType, long startLoc, long taskTargetLoc, string remark,long? equipId = 0,long? productId = 0,string toolTip = null,int taskNo = 0)
    {
        var task = new POWcsTask()
        {
            Id = XID.Nextval,
            TaskNo = taskNo > 0 ? taskNo :K8.LSF.Client.CodeValue( "TaskNo").ToInt(0),
            StartLoc = startLoc,
            CurrentLoc = startLoc,
            TargetLoc = taskTargetLoc,
            IsAbnormal = taskType == EnumTaskType.Abnormal,
            TaskType = (int)taskType,
            TaskStatus = (int)EnumTaskStatus.Executable,
            //TrackId = trackId,
            SkuCode = tireCode,
            CreateTime = DateTime.Now,
            RemarkMemo = remark,
            UseFlag = 1
        };

        if(productId > 0)
        {
            task.ProductId = productId;
        }

        if(equipId > 0)
        {
            task.StartEquip = equipId;
            task.CurrentEquip = equipId;
        }
        else
        {
            task.StartEquip = EquipHelper.GetEquipIdByLocId(startLoc);
            task.CurrentEquip = task.StartEquip;
        }

        if (!string.IsNullOrWhiteSpace(toolTip))
        {
            task.TooltipMemo = toolTip;
        }

        task.TargetEquip = EquipHelper.GetEquipIdByLocId(taskTargetLoc);

        this.m_Db.WcsTasks.Add(task);
        XLogHelper.LogToDb(this.m_Db, $"创建新任务。任务号：{task.TaskNo}，胎号：{tireCode}，任务类型：{taskType}，开始位：{startLoc}，目标位：{taskTargetLoc}", WcsLogMsgLevel.Debug, "创建新任务", task);
        return task;
    }


    /// <summary>
    /// 添加指令
    /// </summary>
    public POWcsTaskCmd AddTaskCmd(POWcsTask task, long startLoc, long targetLoc, string remark)
    {
        var taskCmd = new POWcsTaskCmd()
        {
            Id = XID.Nextval,
            TaskId = task.Id,
            TaskNo = task.TaskNo,
            TaskType = task.TaskType,
            EquipId = task.CurrentEquip,
            StartLoc = startLoc,
            TargetLoc = targetLoc,
            CmdType = (int)task.TaskType,
            CmdStatus = (int)EnumTaskCmdStatus.Executable,
            CreateTime = DateTime.Now,
            UseFlag = 1,
            RemarkMemo = remark
        };

        this.m_Db.WcsTaskCmds.Add(taskCmd);
        XLogHelper.LogToDb(this.m_Db, $"创建新指令。任务号：{task.TaskNo}，开始位置：{taskCmd.StartLoc}，目标位置：{taskCmd.TargetLoc}", WcsLogMsgLevel.Debug, "创建新指令", task);
        return taskCmd;
    }
    /// <summary>
    /// 创建指令（附带类型）
    /// </summary>
    /// <param name="task"></param>
    /// <param name="type"></param>
    /// <param name="startLoc"></param>
    /// <param name="targetLoc"></param>
    /// <param name="remark"></param>
    /// <returns></returns>
    public POWcsTaskCmd AddTaskCmdWithNewType(POWcsTask task, int type, long startLoc, long targetLoc,decimal angle = 0, string remark = "")
    {
        var taskCmd = new POWcsTaskCmd()
        {
            Id = XID.Nextval,
            TaskId = task.Id,
            TaskNo = task.TaskNo,
            TaskType = task.TaskType,
            EquipId = task.CurrentEquip,
            StartLoc = startLoc,
            TargetLoc = targetLoc,
            CmdType = type,
            CmdStatus = (int)EnumTaskCmdStatus.Executable,
            CreateTime = DateTime.Now,
            UseFlag = 1,
        };

        if (!remark.IsNullOrWhiteSpace())
        {
            taskCmd.RemarkMemo = remark;
        }

        if(angle > 0)
        {
            taskCmd.SpinAngle = angle;
        }

        this.m_Db.WcsTaskCmds.Add(taskCmd);
        XLogHelper.LogToDb(this.m_Db, $"创建新指令（附带类型）。任务号：{task.TaskNo}，开始位置：{taskCmd.StartLoc}，目标位置：{taskCmd.TargetLoc}", WcsLogMsgLevel.Debug, "创建新指令", task);
        return taskCmd;
    }

    /// <summary>
    /// 执行任务和指令
    /// </summary>
    public void ExecuteTaskAndCmd(TaskAndCmd taskAndCmd, long equipId)
    {
        var now = DateTime.Now;
        if (taskAndCmd.Task.TaskStatus != (int)EnumTaskStatus.Executed)
        {
            taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Executed;
            taskAndCmd.Task.UpdateTime = now;
            XLogHelper.LogToDb(this.m_Db, $"任务号为{taskAndCmd.Task.TaskNo}的任务状态改为已执行", WcsLogMsgLevel.Debug, "执行任务", taskAndCmd.Task);
        }

        taskAndCmd.TaskCmd.CmdStatus = (int)EnumTaskCmdStatus.Executed;
        taskAndCmd.TaskCmd.UpdateTime = now;
        taskAndCmd.TaskCmd.EquipId = equipId;
        XLogHelper.LogToDb(this.m_Db, $"任务号为{taskAndCmd.TaskCmd.TaskNo}的指令状态改为已执行", WcsLogMsgLevel.Debug, "执行指令", taskAndCmd.TaskCmd);
    }

    /// <summary>
    /// 结束任务
    /// </summary>
    public void FinishTask(POWcsTask task, string remark)
    {
        task.TaskStatus = (int)EnumTaskStatus.Finish;
        var taskCmds = this.m_Db.WcsTaskCmds.Where(item => item.TaskId == task.Id).ToList();
        foreach (var taskCmd in taskCmds)
        {
            taskCmd.CmdStatus = (int)EnumTaskCmdStatus.Finish;
        }

        if((task?.ProductId ?? 0) > 0)
        {
            BakAndDeleteProduct(task?.ProductId ?? 0);
        }

        if((task?.SummaryId ?? 0) > 0)
        {
            BakAndDeleteSummaryMaster(task?.SummaryId ?? 0, task?.MasterId ?? 0);
        }

        this.SetTaskCurrentLoc(task, task.TargetLoc.Value);
        XLogHelper.LogToDb(this.m_Db, $"完成任务，任务号为：{task.TaskNo}。{remark}", WcsLogMsgLevel.Info, "完成任务", task);

        //更新硫化机送达时间
        this.UpdateCuringSendTime(task?.TargetEquip ?? 0);

        this.BakAndDeleteTask(task, task.TargetLoc.Value, remark);
        if (task.TrackId.HasValue)
        {
            WcsInCuringHelper.Finish(this.m_Db, task.TrackId.Value, task.TargetLoc.Value, !task.IsAbnormal.Value);
        }
    }

    private void UpdateCuringSendTime(long? curingId)
    {
        var curing = this.m_Db.RcsEquipCurings.Where(f => f.Id == curingId).FirstOrDefault();

        if (curing is not null)
        {
            curing.SendTime = DateTime.Now;
        }
    }

    /// <summary>
    /// 结束指令
    /// </summary>
    public void FinishTaskCmd(TaskAndCmd taskAndCmd, bool ifSetTaskCurrentLoc, string remark = null)
    {
        taskAndCmd.TaskCmd.CmdStatus = (int)EnumTaskCmdStatus.Finish;
        if (ifSetTaskCurrentLoc)
        {
            this.SetTaskCurrentLoc(taskAndCmd.Task, taskAndCmd.TaskCmd.TargetLoc.Value);
        }

        var bakTaskCmd = taskAndCmd.TaskCmd.ToJson().ToObject<POBakWcsTaskCmd>();
        bakTaskCmd.BackTime = DateTime.Now;
        this.m_Db.BakWcsTaskCmds.Add(bakTaskCmd);
        this.m_Db.WcsTaskCmds.Remove(taskAndCmd.TaskCmd);

        XLogHelper.LogToDb(this.m_Db, $"完成指令，指令Id为{taskAndCmd.TaskCmd.Id}", WcsLogMsgLevel.Debug, "完成指令", taskAndCmd.TaskCmd);
    }

    /// <summary>
    /// 设置任务的当前位置
    /// </summary>
    public void SetTaskCurrentLoc(POWcsTask task, long locId)
    {
        task.CurrentLoc = locId;
        task.CurrentEquip = EquipHelper.GetEquipIdByLocId(locId);
        XLogHelper.LogToDb(this.m_Db, $"任务号为{task.TaskNo}的任务设置当前位置为{locId}", WcsLogMsgLevel.Debug, "更新位置", task);
    }

    /// <summary>
    /// 备份并删除任务
    /// </summary>
    private void BakAndDeleteTask(POWcsTask task, long finishLoc, string remark = "")
    {
        var taskCmds = this.m_Db.WcsTaskCmds.Where(item => item.TaskId == task.Id).ToList();
        foreach (var taskCmd in taskCmds)
        {
            var bakTaskCmd = taskCmd.ToJson().ToObject<POBakWcsTaskCmd>();
            if(!bakTaskCmd.BackTime.HasValue)
                bakTaskCmd.BackTime = DateTime.Now;
            this.m_Db.BakWcsTaskCmds.Add(bakTaskCmd);
            this.m_Db.WcsTaskCmds.Remove(taskCmd);
        }
        if (!string.IsNullOrWhiteSpace(remark))
        {
            task.RemarkMemo = task.RemarkMemo +" | "+ remark;
        }
        task.FinishLoc = finishLoc;

        var bakTask = task.ToJson().ToObject<POBakWcsTask>();
        bakTask.BackTime = DateTime.Now;
        this.m_Db.BakWcsTasks.Add(bakTask);
        this.m_Db.WcsTasks.Remove(task);

        XLogHelper.LogToDb(this.m_Db, $"备份删除任务:{task.TaskNo}。{remark}", WcsLogMsgLevel.Debug, "备份删除任务", task);
    }


    /// <summary>
    /// 备份并删除任务
    /// </summary>
    private void BakAndDeleteTask(POWcsTask task,long? cmdId, long finishLoc, string remark = "")
    {
        var taskCmds = this.m_Db.WcsTaskCmds.Where(item => item.TaskId == task.Id && item.Id != cmdId).ToList();
        foreach (var taskCmd in taskCmds)
        {
            var bakTaskCmd = taskCmd.ToJson().ToObject<POBakWcsTaskCmd>();
            if (!bakTaskCmd.BackTime.HasValue)
                bakTaskCmd.BackTime = DateTime.Now;
            this.m_Db.BakWcsTaskCmds.Add(bakTaskCmd);
            this.m_Db.WcsTaskCmds.Remove(taskCmd);
        }
        if (!string.IsNullOrWhiteSpace(remark))
        {
            task.RemarkMemo = task.RemarkMemo + " | " + remark;
        }
        task.FinishLoc = finishLoc;

        var bakTask = task.ToJson().ToObject<POBakWcsTask>();
        bakTask.BackTime = DateTime.Now;
        this.m_Db.BakWcsTasks.Add(bakTask);
        this.m_Db.WcsTasks.Remove(task);

        XLogHelper.LogToDb(this.m_Db, $"备份删除任务:{task.TaskNo}。{remark}", WcsLogMsgLevel.Debug, "备份删除任务", task);
    }

    /// <summary>
    /// 备份删除指令
    /// </summary>
    /// <param name="cmd"></param>
    private void BakAndDeleteCmd(POWcsTaskCmd cmd)
    {
        var bakCmd = cmd.ToJson().ToObject<POBakWcsTaskCmd>();
        if(!bakCmd.BackTime.HasValue)
            bakCmd.BackTime = DateTime.Now;

        this.m_Db.BakWcsTaskCmds.Add(bakCmd);
        this.m_Db.WcsTaskCmds.Remove(cmd);
        XLogHelper.LogToDb(this.m_Db, $"备份删除指令，指令信息：{cmd.ToJson()}", WcsLogMsgLevel.Info, "备份删除指令", cmd);
    }

    /// <summary>
    /// 备份删除产品
    /// </summary>
    /// <param name="cmd"></param>
    private void BakAndDeleteProduct(long productId)
    {
        var product = this.m_Db.ProdProducts.Where(f => f.Id == productId).FirstOrDefault();

        if(product is null)
        {
            return;
        }

        this.m_Db.BakProdProducts.Add(product.ToJson().ToObject<POBakProdProduct>());
        this.m_Db.ProdProducts.Remove(product);
        XLogHelper.LogToDb(this.m_Db, $"备份删除产品，产品信息：{product.ToJson()}", WcsLogMsgLevel.Info, "备份删除产品", product);
    }

    private void BakAndDeleteSummaryMaster(long summaryId,long masterId)
    {
        var summays = this.m_Db.WmsOutOrderSummarys.Where(f => f.MasterId == masterId).ToList();

        if(summays.Count() == 1)
        {
            var summary = summays.FirstOrDefault();

            if((summary?.Id??0) == summaryId)
            {
                BakAndDeleteMaster(masterId);
            }
        }

        BakAndDeleteSummary(summaryId);
    }

    /// <summary>
    /// 备份删除订单
    /// </summary>
    /// <param name="cmd"></param>
    private void BakAndDeleteSummary(long summaryId)
    {
        var summary = this.m_Db.WmsOutOrderSummarys.Where(f => f.Id == summaryId).FirstOrDefault();

        if (summary is null)
        {
            return;
        }

        this.m_Db.BakWmsOutOrderSummarys.Add(summary.ToJson().ToObject<POBakWmsOutOrderSummary>());
        this.m_Db.WmsOutOrderSummarys.Remove(summary);
        XLogHelper.LogToDb(this.m_Db, $"备份删除订单，订单信息：{summary.ToJson()}", WcsLogMsgLevel.Info, "备份删除订单", summary?.Id ?? 0);
    }

    /// <summary>
    /// 备份删除订单主表
    /// </summary>
    /// <param name="cmd"></param>
    private void BakAndDeleteMaster(long masterId)
    {
        var master = this.m_Db.WmsOutOrderMasters.Where(f => f.Id == masterId).FirstOrDefault();

        if (master is null)
        {
            return;
        }

        this.m_Db.BakWmsOutOrderMasters.Add(master.ToJson().ToObject<POBakWmsOutOrderMaster>());
        this.m_Db.WmsOutOrderMasters.Remove(master);
        XLogHelper.LogToDb(this.m_Db, $"备份删除订单主表，订单主表信息：{master.ToJson()}", WcsLogMsgLevel.Info, "备份删除订单主表", master?.Id ?? 0);
    }

    /// <summary>
    /// 重定向到异常口（结束当前任务，创建新的异常任务）
    /// </summary>
    public TaskAndCmd RedirectToAbnormalLoc(TaskAndCmd taskAndCmd, long startLoc, string remark)
    {
        XLogHelper.LogToDb(this.m_Db, $"开始将任务{taskAndCmd.Task.TaskNo}重定向到异常口，开始位：{startLoc}。原因：{remark}", WcsLogMsgLevel.Info, "重定向到异常口", taskAndCmd.Task);

        if (taskAndCmd.Task.GroupNo.HasValue)
        {
            this.ClearGroupNo(taskAndCmd, remark);
        }

        //this.BakAndDeleteTask(taskAndCmd.Task, startLoc, remark);

        return this.EditorTaskAndCmdToAbnormal(taskAndCmd, startLoc, remark);
    }

    public void ClearGroupNo(TaskAndCmd taskAndCmd, string remark)
    {
        int groupNo = taskAndCmd.Task.GroupNo.Value;

        var tasks = this.m_Db.WcsTasks.Where(item => item.GroupNo == groupNo).ToList();
        foreach (var task in tasks)
        {
            task.GroupNo = null;
        }

        XLogHelper.LogToDb(this.m_Db, $"取消任务分组{groupNo}。任务号:{string.Join(",", tasks.Select(item => item.TaskNo))}。{remark}", WcsLogMsgLevel.Warning, "取消分组", taskAndCmd.Task);
    }

    #endregion

    #region 入库全景扫描位置
    public TaskAndCmd AddNewTaskAndCmdForScanLoc(long scanLoc, TireInfo tireInfo,long targetLoc,int? groupNo)
    {
        var inWareHouseTire = WcsInWarehouseHelpers.Add(this.m_Db, tireInfo);

        var material = this.AddProdMaterial(tireInfo);

        var product = AddProduct(tireInfo, material.Id);

        var taskAndCmd = this.AddWareScanTaskAndCmd(inWareHouseTire.Id,product.Id, tireInfo.TireCode, EnumTaskType.Transportation, scanLoc, targetLoc,groupNo,null);

        XLogHelper.LogToDb(this.m_Db, $"胎号{tireInfo.TireCode}设置目标取货位为：{targetLoc}。任务号{taskAndCmd.Task.TaskNo}。组号{groupNo}", WcsLogMsgLevel.Info, "分拣目标取货位", taskAndCmd.Task);
        return taskAndCmd;
    }
    /// <summary>
    /// 添加立库扫描任务和指令
    /// </summary>
    public TaskAndCmd AddWareScanTaskAndCmd(long? trackId,long? productId, string tireCode, EnumTaskType taskType, long startLoc, long targetLoc, int? groupNo,  string remark)
    {
        var task = this.AddWareScanTask(trackId,productId, tireCode, taskType, startLoc, targetLoc, groupNo, remark);
        var taskCmd = this.AddTaskCmd(task, startLoc, targetLoc, remark);

        return new TaskAndCmd()
        {
            Task = task,
            TaskCmd = taskCmd
        };
    }

    private POProdMaterial AddProdMaterial(TireInfo tireInfo)
    {
        var material = this.m_Db.ProdMaterials.Where(f => f.Spec == tireInfo.MaterialCode).FirstOrDefault();

        if(material is not null)
        {
            return material;
        }
        var bean = new POProdMaterial()
        {
            Id = XID.Nextval,
            MaterialCode = tireInfo.MaterialCode,
            MaterialName = tireInfo.MaterialDesc,
            MaterialHeight = tireInfo.Height,
            InsideDiameter = Convert.ToDecimal(tireInfo.Size),
            Spec = tireInfo.MaterialCode,
        };

        this.m_Db.ProdMaterials.Add(bean);
        XLogHelper.LogToDb(this.m_Db, $"创建物料信息。物料：{tireInfo.MaterialCode}，【入参：{tireInfo.ToJson()}】", WcsLogMsgLevel.Debug, "创建物料", bean);
        return bean;
    }

    private POProdProduct AddProduct(TireInfo tireInfo,long? materialId)
    {
        var product = this.m_Db.ProdProducts.Where(f => f.ProductCode == tireInfo.TireCode).FirstOrDefault();

        if(product is not null)
        {
            return product;
        }

        var bean = new POProdProduct()
        {
            Id = XID.Nextval,
            ProductCode = tireInfo.TireCode,
            MaterialCode = tireInfo.MaterialCode,
            MaterialDesc = tireInfo.MaterialDesc,
            Height = tireInfo.Height,
            Size = tireInfo.Size,
            ProdDt = tireInfo.ProdDt,
            TbmNo = tireInfo.TbmNo,
            MaterialId = materialId,
            TbmPs = tireInfo.TbmPs,
            OutTime = tireInfo.TbmExpirationTime,
        };

        this.m_Db.ProdProducts.Add(bean);
        XLogHelper.LogToDb(this.m_Db, $"创建产品信息。胎号：{tireInfo.TireCode}，【入参：{tireInfo.ToJson()}】", WcsLogMsgLevel.Debug, "创建产品", bean);
        return bean;
    }

    /// <summary>
    /// 添加入库任务
    /// </summary>
    public POWcsTask AddWareScanTask(long? trackId,long? productId, string tireCode, EnumTaskType taskType, long startLoc, long taskTargetLoc, int? groupNo, string remark)
    {
        var taskNo = CodeHelper.NextValue("InTaskNo").ToInt(0);

        if((groupNo ?? 0) <= 0)
        {
            groupNo = taskNo;
        }

        var task = new POWcsTask()
        {
            Id = XID.Nextval,
            TaskNo = taskNo,
            GroupNo = groupNo,
            StartLoc = startLoc,
            CurrentLoc = startLoc,
            TargetLoc = taskTargetLoc,
            IsAbnormal = taskType == EnumTaskType.Abnormal,
            TaskType = (int)taskType,
            TaskStatus = (int)EnumTaskStatus.Executable,
            TrackId = trackId,
            ProductId = productId,
            SkuCode = tireCode,
            CreateTime = DateTime.Now,
            RemarkMemo = remark,
            UseFlag = 1
        };

        task.StartEquip = EquipHelper.GetEquipIdByLocId(startLoc);
        task.CurrentEquip = task.StartEquip;
        task.TargetEquip = EquipHelper.GetEquipIdByLocId(taskTargetLoc);

        this.m_Db.WcsTasks.Add(task);
        XLogHelper.LogToDb(this.m_Db, $"创建新任务。任务号：{task.TaskNo}，胎号：{tireCode}，任务类型：{taskType}，开始位：{startLoc}，目标位：{taskTargetLoc}", WcsLogMsgLevel.Debug, "创建新任务", task);
        return task;
    }

    public void UpdateInScanExcuteTime(long inWarehouseId)
    {
        WcsInWarehouseHelpers.UpdateScanExcuteTime(this.m_Db, inWarehouseId);
    }

    #endregion

    #region 堆垛机入库

    internal TaskAndCmd EditTaskAndCreateCmd(TaskDTO taskDTO)
    {
        var taskId = taskDTO.TaskId;
        var targetLoc = taskDTO.TargetLoc;
        var status = taskDTO.Status;
        var type = taskDTO.Type;
        var startEquip = taskDTO.StartEquip;
        var startLoc = taskDTO.StartLoc;
        var groupNo = taskDTO.GroupNo;
        var groupIndex = taskDTO.GroupIndex;

        var task = this.m_Db.WcsTasks.Where(f => f.Id == taskId).FirstOrDefault();

        if(task is not null)
        {
            var oldCmd = this.m_Db.WcsTaskCmds.Where(f => f.TaskId == taskId).FirstOrDefault();

            if(oldCmd is not null)
            {
                oldCmd.CmdStatus = (int)EnumTaskStatus.Finish;
                oldCmd.FinishTime = DateTime.Now;
                BakAndDeleteCmd(oldCmd);

                XLogHelper.LogToDb(this.m_Db, $"入库-备份删除，扫描到取货位的指令", WcsLogMsgLevel.Info, "备份入库输送指令", oldCmd);
            }

            WcsInWarehouseHelpers.UpdateCrnCreateTime(this.m_Db, task?.TrackId ?? 0);

            task.StartLoc = startLoc;
            task.StartEquip = startEquip;
            task.CurrentEquip = startEquip;
            task.CurrentLoc = startLoc;
            task.TargetLoc = targetLoc;
            task.TaskStatus = status;
            task.TaskGroup = groupNo;
            task.TaskGroupIndex = groupIndex;
            task.TaskType = type;

            XLogHelper.LogToDb(this.m_Db, $"入库-修改入库任务，选取目标位为：{targetLoc}", WcsLogMsgLevel.Info, "修改为入库任务", task);

            var newCmd = new POWcsTaskCmd()
            {
                Id = XID.Nextval,
                TaskId = task.Id,
                TaskNo = task.TaskNo,
                TaskType = type,
                EquipId = startEquip,
                StartLoc = startLoc,
                CurrentLoc = startLoc,
                TargetLoc = targetLoc,
                CmdStatus = status,
                CmdType = type,
            };

            this.m_Db.WcsTaskCmds.Add(newCmd);
            XLogHelper.LogToDb(this.m_Db, $"创建入库指令，选取目标位：{targetLoc},详细信息：{newCmd.ToJson()}", WcsLogMsgLevel.Info, "创建入库指令", oldCmd);

            return new TaskAndCmd { Task = task, TaskCmd = newCmd };
        }

        return null;
    }

    internal void ExcuteInWarehouseTask(int taskNo,long locId)
    {
        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds,f => f.Id,s => s.TaskId,(f,s) => new
        {
            Task = f,
            Cmd = s,
        }).Where(f => f.Task.TaskNo == taskNo).FirstOrDefault();

        if(taskAndCmd is not null)
        {
            if(taskAndCmd.Task.TaskStatus != (int)EnumTaskCmdStatus.Executable)
            {
                WriteLog($"任务不是可执行状态，当前状态：{taskAndCmd.Task.TaskStatus}");

                return;
            }

            if (taskAndCmd.Task.TaskType != (int)EnumTaskType.Warehousing)
            {
                WriteLog($"任务类型不是入库任务，当前任务：{taskAndCmd.Task.TaskType}");

                return;
            }

            SetCrnType(taskAndCmd?.Cmd?.EquipId ?? 0, taskAndCmd?.Task?.TaskType ?? 0);

            WcsInWarehouseHelpers.UpdateCrnUpdateTime(this.m_Db, taskAndCmd?.Task?.TrackId ?? 0);

            taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Executed;
            taskAndCmd.Cmd.CmdStatus = (int)EnumTaskStatus.Executed;
            taskAndCmd.Task.UpdateTime = DateTime.Now;
            taskAndCmd.Cmd.UpdateTime = DateTime.Now;

            XLogHelper.LogToDb(this.m_Db, $"入库-下发堆垛机入库任务-{taskAndCmd.Task.Id}，修改状态", WcsLogMsgLevel.Info, "下发入库任务", taskAndCmd.Task);
        }
    }

    internal void FinishCrnTask(int taskNo, long locId)
    {
        var manager = new LocSkuManager(this.m_Db);

        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new
        {
            Task = f,
            Cmd = s,
        }).Where(f => f.Task.TaskNo == taskNo && f.Task.TaskStatus == (int)EnumTaskCmdStatus.Executed).FirstOrDefault();

        if(taskAndCmd is not null)
        {
            if (taskAndCmd.Task.TaskStatus != (int)EnumTaskCmdStatus.Executed)
            {
                WriteLog($"任务不是已执行状态，当前状态：{taskAndCmd.Task.TaskStatus}");

                return;
            }

            if (taskAndCmd.Task.TaskType != (int)EnumTaskType.Warehousing)
            {
                WriteLog($"任务类型不是入库任务，当前任务：{taskAndCmd.Task.TaskType}");

                return;
            }

            var mesRes = this.SyncInEnd(taskAndCmd?.Task?.SkuCode ?? "", locId);

            if (mesRes <= 0)
            {
                if (mesRes == -1)
                {
                    WriteLog($"回写Mes--未找到入库信息，条码：{taskAndCmd?.Task?.SkuCode ?? ""}");
                }
                else if (mesRes == -2)
                {
                    WriteLog($"回写Mes--未找到库位信息，库位：{locId}");
                }
                else
                {
                    WriteLog($"回写Mes--失败，结果：{mesRes}");
                }

                return;
            }

            WcsInWarehouseHelpers.UpdateCrnFinishTime(this.m_Db, taskAndCmd?.Task?.TrackId ?? 0, taskAndCmd?.Task?.TargetLoc ?? 0);

            taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Finish;
            taskAndCmd.Cmd.CmdStatus = (int)EnumTaskStatus.Finish;

            XLogHelper.LogToDb(this.m_Db, $"入库完成-更改任务/指令状态-{taskAndCmd.Task.Id}", WcsLogMsgLevel.Info, "完成更改状态", taskAndCmd.Task);

            var product = this.m_Db.ProdProducts.Where(f => f.Id == taskAndCmd.Task.ProductId).FirstOrDefault();

            manager.UpdateLocationAndWcsLocWithSkuId(locId, taskAndCmd?.Task?.ProductId ?? 0, product?.MaterialId ?? 0, taskAndCmd?.Task?.Id ?? 0, taskAndCmd.Task.SkuCode, taskAndCmd?.Task?.TaskType ?? 0,false);

            BakAndDeleteTask(taskAndCmd.Task,locId,"");
        }
    }

    public int SyncInEnd(string SkuCode,long locId)
    {
        var loc = this.m_Db.RcsLocations.Where(f => f.Id == locId).FirstOrDefault();

        if(loc is null)
        {
            return -2;
        }

        var mesService = RpcHelper.Create<IMesService>();

        return mesService.AddInEndByBcdNos(SkuCode, loc?.LocCode ?? "");

    }

    public void OperateIfHaveGood(long? oldTargetLoc,long? taskId,long? newTargetLoc)
    {
        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new TaskAndCmd
        {
            Task = f,
            TaskCmd = s,
        }).Where(f => f.Task.Id == taskId).FirstOrDefault();

        if(taskAndCmd is not null)
        {
            var loc = this.m_Db.RcsLocations.Where(f => f.Id == oldTargetLoc).FirstOrDefault();

            if(loc is not null)
            {
                loc.LocEnable = 0;
                loc.ErrInHas = 1;
                loc.Remarks = $"程序-入库时有货，任务Id：{taskId}";

                XLogHelper.LogToDb(this.m_Db, $"入库-{taskId}-入库时有货，禁用库位：{oldTargetLoc}", WcsLogMsgLevel.Info, "禁用货位", oldTargetLoc);
            }

            taskAndCmd.Task.TargetLoc = newTargetLoc;
            taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Executable;
            taskAndCmd.Task.UpdateTime = DateTime.Now;
            taskAndCmd.Task.ExcuteHaveGood = 1;

            XLogHelper.LogToDb(this.m_Db, $"入库-{taskId}-入库时有货,更改任务目标位，原目标位：{oldTargetLoc}，新目标位：{newTargetLoc}", WcsLogMsgLevel.Info, "更改任务目标位", taskAndCmd.Task);

            taskAndCmd.TaskCmd.TargetLoc = newTargetLoc;
            taskAndCmd.TaskCmd.CmdStatus = (int)EnumTaskStatus.Executable;
            taskAndCmd.TaskCmd.UpdateTime = DateTime.Now;

            XLogHelper.LogToDb(this.m_Db, $"入库-{taskId}-入库时有货，更改指令目标位，原目标位：{oldTargetLoc}，新目标位：{newTargetLoc}", WcsLogMsgLevel.Info, "更改指令目标位", taskAndCmd.TaskCmd);
        }
    }

    public void ExcuteTaskIfHaveGood(long? taskId)
    {
        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new TaskAndCmd
        {
            Task = f,
            TaskCmd = s,
        }).Where(f => f.Task.Id == taskId).FirstOrDefault();

        if (taskAndCmd is not null)
        {
            taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Executed;
            taskAndCmd.Task.UpdateTime = DateTime.Now;
            taskAndCmd.Task.ExcuteHaveGood = 2;

            XLogHelper.LogToDb(this.m_Db, $"入库-{taskId}-入库时有货,下发入库有货任务", WcsLogMsgLevel.Info, "下发入库有货任务", taskAndCmd.Task);

            taskAndCmd.TaskCmd.CmdStatus = (int)EnumTaskStatus.Executed;
            taskAndCmd.TaskCmd.UpdateTime = DateTime.Now;

            XLogHelper.LogToDb(this.m_Db, $"入库-{taskId}-入库时有货，下发入库有货指令", WcsLogMsgLevel.Info, "下发入库有货指令", taskAndCmd.TaskCmd);
        }
    }

    #endregion

    #region 堆垛机出库

    public void UpdateSummaryRemarkByIds(List<long?> sumamryIds,string remarks)
    {
        var manager = new SummaryManager(this.m_Db);

        foreach (var summaryId in sumamryIds)
        {
            manager.UpdateSummaryRemarksById(summaryId, remarks);
        }
    }

    public void ExcuteOutTask(int taskNo,long trackId,int status)
    {
        WcsInCuringHelper.UpdateCrnUpdateTime(this.m_Db, trackId);

        UpdateTaskAndCmdStatus(taskNo, status);
    }

    public void FinishOutTask(long taskId,long materialId,long locId,int? orderType,bool bakTask = false)
    {
        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new TaskAndCmd
        {
            Task = f,
            TaskCmd = s,
        }).Where(f => f.Task.Id == taskId).FirstOrDefault();

        if(taskAndCmd is not null)
        {
            var manager = new LocSkuManager(this.m_Db);

            var trackId = taskAndCmd?.Task?.TrackId ?? 0;
            var productId = taskAndCmd?.Task?.ProductId ?? 0;
            var skuCode = taskAndCmd?.Task?.SkuCode;
            var cmdTargetLoc = taskAndCmd?.TaskCmd?.TargetLoc ?? 0;
            var taskType = taskAndCmd?.Task?.TaskStatus ?? 0;

            WcsInCuringHelper.UpdateCrnFinishTime(this.m_Db, trackId);

            manager.UpdateLocationAndWcsLocWithSkuId(cmdTargetLoc,productId,materialId,taskId,skuCode, taskType);


            taskAndCmd.Task.CmdTargetLoc = taskAndCmd.TaskCmd.TargetLoc;
            taskAndCmd.TaskCmd.FinishTime = DateTime.Now;
            taskAndCmd.TaskCmd.CmdStatus = (int)EnumTaskStatus.Finish;
            BakAndDeleteCmd(taskAndCmd.TaskCmd);

            XLogHelper.LogToDb(this.m_Db, $"出库完成-备份删除出库指令", WcsLogMsgLevel.Info, "备份出库指令", taskAndCmd.TaskCmd);

            if (bakTask)
            {
                if ((taskAndCmd?.Task?.ProductId ?? 0) > 0)
                {
                    BakAndDeleteProduct(taskAndCmd?.Task?.ProductId ?? 0);
                }

                if ((taskAndCmd?.Task?.SummaryId ?? 0) > 0)
                {
                    BakAndDeleteSummaryMaster(taskAndCmd?.Task?.SummaryId ?? 0, taskAndCmd?.Task?.MasterId ?? 0);
                }
                manager.ClearLocHasTask(cmdTargetLoc);

                taskAndCmd.Task.FinishTime = DateTime.Now;
                taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Finish;
                BakAndDeleteTask(taskAndCmd.Task, taskAndCmd?.TaskCmd?.Id ?? 0, locId);
                

                XLogHelper.LogToDb(this.m_Db, $"出库完成-备份删除出库任务，订单类型为：{orderType} 是否-{orderType == (int)EnumCodeOutOrderType.WarehouseLocationLocUnderCrn}-出库到堆垛机异常口", WcsLogMsgLevel.Info, "备份出库任务", taskAndCmd.Task);
            }
        }
    }

    public void SplitSummaryMasters(long? summaryId,int orderType)
    {
        var manager = new SummaryManager(this.m_Db);

        var master = manager.AddOutMasters(orderType);

        manager.SplitSummaryById(summaryId, master.Id);
    }

    public TaskAndCmd AddNewTaskAndCmdOfExWarehouse(POWmsOutOrderSummary summary,POWcsForkLoc forkOutput,PORcsEquipCuring curing,POProdProduct product,long? startLoc,int groupNo = 0)
    {
        if(summary is null || forkOutput is null || curing is null || product is null)
        {

            if(summary is not null)
            {
                var remark = $"创建任务时，参数不全，【(forkOutput is null : {forkOutput is null})-(curing is null : {curing is null})-(product is null : {product is null}) 】 | {DateTime.Now}";

                this.UpdateSummaryRemarkByIds(new List<long?> { summary.Id }, remark);
            }

            return null;
        }

        var manager = new SummaryManager(this.m_Db);

        manager.UpdateSummaryStartLocAndRealCount(summary.Id, startLoc);

        var (tireInfo, tcmInfo, curingInfo) = CreateInCuringMsg(summary, curing, product);

        var inCuringTire = WcsInCuringHelper.Add(this.m_Db, tireInfo, tcmInfo, curingInfo, false,true);

        var taskAndCmd = this.AddExWarehouseTaskAndCmd(inCuringTire.Id, inCuringTire.TireCode, EnumTaskType.Exwarehouse, startLoc ?? 0, curingInfo.Loc, forkOutput.LocId ?? 0, null, summary, forkOutput.ForkId, product.Id,$"【{tcmInfo.TCM_NO}-{tcmInfo.TCM_DIR}】--{summary.SkuBatch}");
        taskAndCmd.Task.CuringOrder = curingInfo.Order;
        taskAndCmd.Task.CuringDitch = curingInfo.DitchId;

        if (groupNo > 0)
        {
            taskAndCmd.Task.TaskGroup = groupNo;
        }

        var taskId = taskAndCmd?.Task?.Id ?? 0;

        var locSkuManger = new LocSkuManager(this.m_Db);

        locSkuManger.SetLocTask(startLoc, taskId);

        XLogHelper.LogToDb(this.m_Db, $"胎号{tireInfo.TireCode}生成出库任务，目标硫化机为{curingInfo.DitchId}排{taskAndCmd.Task.CuringOrder}号。任务号{taskAndCmd.Task.TaskNo}", WcsLogMsgLevel.Info, "生成出库任务", taskAndCmd.Task);
        return taskAndCmd;
    }

    public TaskAndCmd AddAbnormalTaskAndCmdOfExWarehouse(POWmsOutOrderSummary summary, POWcsForkLoc forkOutput, POProdProduct product, long? startLoc, int groupNo = 0)
    {
        if (summary is null || forkOutput is null || product is null)
        {

            if (summary is not null)
            {
                var remark = $"创建任务时，参数不全，【(forkOutput is null : {forkOutput is null})-(product is null : {product is null}) 】 | {DateTime.Now}";

                this.UpdateSummaryRemarkByIds(new List<long?> { summary.Id }, remark);
            }

            return null;
        }

        var manager = new SummaryManager(this.m_Db);

        manager.UpdateSummaryStartLocAndRealCount(summary.Id, startLoc);

        var taskAndCmd = this.AddExWarehouseTaskAndCmd(null, product.ProductCode, EnumTaskType.Abnormal, startLoc ?? 0, summary?.TargetLoc ?? 0, forkOutput.LocId ?? 0, null,summary, forkOutput.ForkId, product.Id);

        if (groupNo > 0)
        {
            taskAndCmd.Task.TaskGroup = groupNo;
        }

        var taskId = taskAndCmd?.Task?.Id ?? 0;

        var locSkuManger = new LocSkuManager(this.m_Db);

        locSkuManger.SetLocTask(startLoc, taskId);

        XLogHelper.LogToDb(this.m_Db, $"胎号{product.ProductCode}生成异常出库任务，起始位置是：{startLoc}。任务号{taskAndCmd.Task.TaskNo}", WcsLogMsgLevel.Info, "生成异常出库任务", taskAndCmd.Task);
        return taskAndCmd;
    }

    private TaskAndCmd AddExWarehouseTaskAndCmd(long? trackId, string tireCode, EnumTaskType taskType, long startLoc, long taskTargetLoc, long taskCmdTargetLoc, string remark,POWmsOutOrderSummary summary, long? equipId = 0, long? productId = 0, string toolTip = null)
    {
        var task = this.AddExWareHouseTask(trackId, tireCode, taskType, startLoc, taskTargetLoc, remark,summary, equipId, productId,toolTip);

        if(task.TaskType == (int)EnumTaskType.Abnormal)
        {
            var cmd = AddTaskCmdWithNewType(task, (int)EnumTaskType.Exwarehouse, startLoc, taskCmdTargetLoc, 0, remark);
            return new TaskAndCmd()
            {
                Task = task,
                TaskCmd = cmd
            };
        }

        var taskCmd = this.AddTaskCmd(task, startLoc, taskCmdTargetLoc, remark);
        return new TaskAndCmd()
        {
            Task = task,
            TaskCmd = taskCmd
        };
    }

    /// <summary>
    /// 添加任务
    /// </summary>
    public POWcsTask AddExWareHouseTask(long? trackId, string tireCode, EnumTaskType taskType, long startLoc, long taskTargetLoc, string remark,POWmsOutOrderSummary summary, long? equipId = 0, long? productId = 0, string toolTip = null)
    {
        var task = new POWcsTask()
        {
            Id = XID.Nextval,
            TaskNo = CodeHelper.NextValue("TaskNo").ToInt(0),
            StartLoc = startLoc,
            CurrentLoc = startLoc,
            TargetLoc = taskTargetLoc,
            IsAbnormal = taskType == EnumTaskType.Abnormal,
            TaskType = (int)taskType,
            TaskStatus = (int)EnumTaskStatus.Executable,
            TrackId = trackId,
            SkuCode = tireCode,
            CreateTime = DateTime.Now,
            RemarkMemo = remark,
            UseFlag = 1,
            SummaryId = summary?.Id,
            MasterId = summary?.MasterId,
            ForkId = equipId,
        };

        if (productId > 0)
        {
            task.ProductId = productId;
        }

        if (equipId > 0)
        {
            task.StartEquip = equipId;
            task.CurrentEquip = equipId;
        }
        else
        {
            task.StartEquip = EquipHelper.GetEquipIdByLocId(startLoc);
            task.CurrentEquip = task.StartEquip;
        }

        if (!string.IsNullOrWhiteSpace(toolTip))
        {
            task.TooltipMemo = toolTip;
        }

        task.TargetEquip = EquipHelper.GetEquipIdByLocId(taskTargetLoc);

        this.m_Db.WcsTasks.Add(task);
        XLogHelper.LogToDb(this.m_Db, $"创建新任务。任务号：{task.TaskNo}，胎号：{tireCode}，任务类型：{taskType}，开始位：{startLoc}，目标位：{taskTargetLoc}", WcsLogMsgLevel.Debug, "创建新任务", task);
        return task;
    }

    private (TireInfo tireInfo, TcmInfo tcmInfo, CuringInfo curingInfo) CreateInCuringMsg(POWmsOutOrderSummary summary,PORcsEquipCuring curing,POProdProduct product)
    {
        TireInfo tireInfo = new TireInfo()
        {
            TireCode = product.ProductCode,
            MaterialCode = product.MaterialCode,
            MaterialDesc = product.MaterialDesc,
            Size = product.Size ?? 0,
            Height = product.Height ?? 0,
            ProdDt = product.ProdDt ?? DateTime.MaxValue,
            TbmNo = product.TbmNo,
        };


        TcmInfo tcmInfo = new TcmInfo()
        {
            TCM_ANGLE = (int)Math.Ceiling(summary?.RotateAngle ?? 0),
            TBM_PS = summary.TbmPs,
            TCM_SPEC = summary.CuringSpec,
            TCM_SPEC_DESC = summary.CuringSpecDesc,
        };


        CuringInfo curingInfo = new CuringInfo()
        {
            DitchId = curing.DitchId ?? 0,
            Code = curing.CuringCode,
            Dir  = curing.CuringDir,
            Id = curing.Id ?? 0,
            Order = curing.CuringOrder ?? 0,
            Loc = summary.TargetLoc ?? 0,
        };

        return (tireInfo, tcmInfo, curingInfo);
    }


    public void UpdateTaskAndCmdStatus(int? taskNo,int status,string remark = "")
    {
        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new TaskAndCmd
        {
            Task = f,
            TaskCmd = s,
        }).Where(f => f.Task.TaskNo == taskNo).FirstOrDefault();

        if(taskAndCmd is not null)
        {
            taskAndCmd.Task.TaskStatus = status;
            taskAndCmd.TaskCmd.CmdStatus = status;

            if(status == (int)EnumTaskStatus.Executed)
            {
                taskAndCmd.Task.UpdateTime = DateTime.Now;
                taskAndCmd.TaskCmd.UpdateTime = DateTime.Now;
            }

            if (status == (int)EnumTaskStatus.Finish)
            {
                taskAndCmd.TaskCmd.FinishTime = DateTime.Now;
            }

            if (!remark.IsNullOrWhiteSpace())
            {
                taskAndCmd.Task.RemarkMemo = remark;
            }

            XLogHelper.LogToDb(this.m_Db, $"任务：{taskNo},Id：{taskAndCmd?.Task?.Id},胎号：{taskAndCmd?.Task?.SkuCode},更改状态为：{status}", WcsLogMsgLevel.Debug, "更新任务状态", taskAndCmd?.Task);
        }
    }

    public void OperateExcuteIfNoGood(long? taskId,long newStartLoc,bool isSplit = false)
    {
        var taskAndCmd = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new TaskAndCmd
        {
            Task = f,
            TaskCmd = s,
        }).Where(f => f.Task.Id == taskId).FirstOrDefault();

        if(taskAndCmd is not null)
        {
            var oldStartLoc = taskAndCmd?.Task?.StartLoc ?? 0;

            var loc = this.m_Db.RcsLocations.Where(f => f.Id == oldStartLoc).FirstOrDefault();

            if (loc is not null)
            {
                loc.LocEnable = 0;
                loc.ErrOutEmpty = 0;
                loc.Remarks = $"程序-出库取料无货，禁用库位，任务Id：{taskId}";

                XLogHelper.LogToDb(this.m_Db, $"出库-{taskId}-出库时取料无货，禁用库位：{oldStartLoc}", WcsLogMsgLevel.Info, "出库无货", oldStartLoc);
            }


            var summaryId = taskAndCmd?.Task?.SummaryId ?? 0;
            var masterId = taskAndCmd?.Task?.MasterId ?? 0;

            var summary = this.m_Db.WmsOutOrderSummarys.Where(f => f.Id == summaryId).FirstOrDefault();
            var master = this.m_Db.WmsOutOrderMasters.Where(f => f.Id == masterId).FirstOrDefault();

            var orderType = master?.OrderType ?? 0;

            if(summary is not null)
            {
                summary.RealCount = 0;
                summary.StartLoc = null;

                taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Finish;
                taskAndCmd.Task.FinishTime = DateTime.Now;
                taskAndCmd.Task.FinishMode = (int)EnumFinishMode.SystemDelete;
                taskAndCmd.TaskCmd.CmdStatus = (int)EnumTaskStatus.Finish;
                taskAndCmd.TaskCmd.FinishTime = DateTime.Now;
                taskAndCmd.Task.RemarkMemo = $"取料无货，备份删除任务，起始库位：{oldStartLoc}";

                //普通手工出库-一个主订单，一个summary
                if (orderType == (int)EnumCodeOutOrderType.WarehouseLocationLocUnderCrn || orderType == (int)EnumCodeOutOrderType.WarehouseLocationLine)
                {
                    var baksummary = summary.ToJson().ToObject<POBakWmsOutOrderSummary>();
                    var bakmaster = master.ToJson().ToObject<POBakWmsOutOrderMaster>();
                    baksummary.FinishTime = DateTime.Now;
                    baksummary.FinishMode = 1;
                    baksummary.RemarkMemo = $"取料无货，手工出库订单自动结束 | {summary.RemarkMemo}";
                    bakmaster.FinishTime = DateTime.Now;
                    bakmaster.FinishMode = 1;

                    this.m_Db.BakWmsOutOrderSummarys.Add(baksummary);
                    this.m_Db.BakWmsOutOrderMasters.Add(bakmaster);
                    this.m_Db.WmsOutOrderSummarys.Remove(summary);
                    this.m_Db.WmsOutOrderMasters.Remove(master);

                    XLogHelper.LogToDb(this.m_Db, $"出库-{taskId}-出库时取料无货，手工出库订单，自动结束。", WcsLogMsgLevel.Info, "出库无货", summary?.Id);
                }

                var trackId = taskAndCmd?.Task?.TrackId ?? 0;
                if (trackId > 0)
                {
                    var inCuringTire = this.m_Db.WcsInCuringTires.FirstOrDefault(x => x.Id == trackId);

                    WcsInCuringHelper.BakAndDelInCuringTire(this.m_Db, inCuringTire);
                }

                this.BakAndDeleteTask(taskAndCmd.Task, taskAndCmd?.Task?.StartLoc ?? 0, $"出库-{taskId}-出库时取料无货，且未找到新货位，完成备份删除任务");

                XLogHelper.LogToDb(this.m_Db, $"出库-{taskId}-出库时取料无货，完成备份删除任务指令：{oldStartLoc}", WcsLogMsgLevel.Info, "完成无货任务", taskAndCmd.Task);
            }


        }
    }

    #endregion

    #region 堆垛机出库线体
    public void AddNewTaskCmdForOutputs(long taskId,long cmdStartLoc,long cmdTargetLoc,decimal angle,int type)
    {
        var task = this.m_Db.WcsTasks.Where(f => f.Id == taskId).FirstOrDefault();

        if(task is not null)
        {
            var currentEquip = this.m_Db.WcsEquipLocs.Where(f => f.LocId == cmdStartLoc).FirstOrDefault()?.EquipId ?? 0;

            this.SetTaskCurrentLoc(task, cmdStartLoc);

            var cmd = AddTaskCmdWithNewType(task, type, cmdStartLoc, cmdTargetLoc,angle);

            XLogHelper.LogToDb(this.m_Db, $"条码：{task?.SkuCode},生成从出库口：{cmdStartLoc},到目标位：{cmdTargetLoc}的指令，同时更新任务当前设备：{currentEquip}", WcsLogMsgLevel.Info, "出库口创建指令", cmd);
        }
    }

    public void ExcuteOutLineTasks(long taskId)
    {
        var manager = new LocSkuManager(this.m_Db);

        var taskCmd = this.m_Db.WcsTaskCmds.Where(f => f.TaskId == taskId).FirstOrDefault();
        var task = this.m_Db.WcsTasks.Where(f => f.Id == taskId).FirstOrDefault();

        manager.ClearLocHasTask(taskCmd?.StartLoc ?? 0);

        XLogHelper.LogToDb(this.m_Db, $"出库口下发-清除起始位：{taskCmd?.StartLoc ?? 0}的绑定关系，防止多次创建任务", WcsLogMsgLevel.Info, "清除绑定关系", taskCmd?.StartLoc ?? 0);

        if (taskCmd is not null && task is not null)
        {
            if ((task?.TaskType ?? 0) == (int)EnumTaskType.Abnormal)
            {
                this.FinishTask(task, "出库口-异常任务直接完成");

                XLogHelper.LogToDb(this.m_Db, $"出库口-条码：{task?.SkuCode},出库口完成任务", WcsLogMsgLevel.Info, "出库口完成任务", taskCmd);

                return;
            }

            taskCmd.UpdateTime = DateTime.Now;
            taskCmd.CmdStatus = (int)EnumTaskCmdStatus.Executed;

            XLogHelper.LogToDb(this.m_Db, $"出库口-条码：{task?.SkuCode},下发出库线体输送指令", WcsLogMsgLevel.Info, "出库口下发任务", taskCmd);

        }
    }
    
    #endregion

    #region 硫化全景扫描位置

    public TaskAndCmd AddNewTaskAndCmdOfPanramaScanLoc(long panramaScanLoc, TireInfo tireInfo, TcmInfo tcmInfo, CuringInfo curingInfo)
    {
        var inCuringTire = WcsInCuringHelper.Add(this.m_Db, tireInfo, tcmInfo, curingInfo,true);
        var netOutput = PathHelper.GetNormalPath(panramaScanLoc, curingInfo.Loc);

        var taskAndCmd = this.AddTaskAndCmd(inCuringTire.Id, inCuringTire.TireCode, EnumTaskType.Transportation, panramaScanLoc, curingInfo.Loc, netOutput.AngleScanLoc.Value, null,0,0, $"【{tcmInfo.TCM_NO}-{tcmInfo.TCM_DIR}】--{tcmInfo.OrderMsg}");
        taskAndCmd.Task.CuringOrder = curingInfo.Order;
        taskAndCmd.Task.CuringDitch = curingInfo.DitchId;

        XLogHelper.LogToDb(this.m_Db, $"胎号{tireInfo.TireCode}设置目标硫化机为{curingInfo.DitchId}排{taskAndCmd.Task.CuringOrder}号。任务号{taskAndCmd.Task.TaskNo}", WcsLogMsgLevel.Info, "设置目标硫化机", taskAndCmd.Task);
        return taskAndCmd;
    }

    public TaskAndCmd AddNewCmdOfPanramaScanLoc(long panramaScanLoc, long? taskId,long nextCmdTarget)
    {
        var task = this.m_Db.WcsTasks.Where(f => f.Id == taskId).FirstOrDefault();

        if(task is not null)
        {
            if((task?.ForkId ?? 0) > 0)
            {
                FinishLikeNoReadTask(panramaScanLoc, task);
            }

            WcsInCuringHelper.UpdateCuringScanTime(this.m_Db, task?.TrackId ?? 0);

            var oldTaskCmd = this.m_Db.WcsTaskCmds.Where(f => f.TaskId == taskId).FirstOrDefault();

            if (oldTaskCmd is not null)
            {
                oldTaskCmd.CmdStatus = (int)EnumTaskStatus.Finish;
                oldTaskCmd.FinishTime = DateTime.Now;

                BakAndDeleteCmd(oldTaskCmd);
            }

            this.SetTaskCurrentLoc(task, panramaScanLoc);

            var type = (int)EnumTaskType.Transportation;

            if(task.TaskType == (int)EnumTaskType.Abnormal)
            {
                type = (int)EnumTaskType.Abnormal;
            }

            var cmd = AddTaskCmdWithNewType(task, type, panramaScanLoc, nextCmdTarget, oldTaskCmd?.SpinAngle ?? 0);

            XLogHelper.LogToDb(this.m_Db, $"胎号{task?.SkuCode}送往{nextCmdTarget},任务是否异常：{task.IsAbnormal}", WcsLogMsgLevel.Info, "设置目标硫化机", task);

            return new TaskAndCmd { Task = task,TaskCmd = cmd };
        }
        return new TaskAndCmd { };
    }

    private void FinishLikeNoReadTask(long panramaScanLoc, POWcsTask oldTask)
    {
        var TaskCmds = this.m_Db.WcsTasks.Join(this.m_Db.WcsTaskCmds, f => f.Id, s => s.TaskId, (f, s) => new TaskAndCmd
        {
            Task = f,
            TaskCmd = s,
        }).Where(f =>f.Task.Id != oldTask.Id && f.Task.ForkId == oldTask.ForkId && f.TaskCmd.TargetLoc == panramaScanLoc && f.Task.CreateTime < oldTask.CreateTime).ToList();

        if (TaskCmds is not null && TaskCmds.Any())
        {
            foreach (var taskCmd in TaskCmds)
            {
                var task = taskCmd.Task;

                this.FinishTask(task, "硫化扫描位-后创建出库任务先到达扫描位，疑似当前任务胎胚NoRead，自动删除备份");

                XLogHelper.LogToDb(this.m_Db, $"出库口-条码：{task?.SkuCode},出库口完成任务", WcsLogMsgLevel.Info, "出库口完成任务", task);
            }
        }
    }

    public POWcsTask GetLeastTaskOfPanramaScanLoc(long locId)
    {
        return this.m_Db.WcsTasks.FirstOrDefault(t => t.UseFlag == 1 && t.StartLoc == locId);
    }

    public void UpdateCuringScanExcuteTime(long inCuringId)
    {
        WcsInCuringHelper.UpdateCuringScanExcuteTime(this.m_Db, inCuringId);
    }

    #endregion

    #region 角度扫描位

    /// <summary>
    /// 重定向到异常口（结束当前任务，创建新的异常任务）
    /// </summary>
    public TaskAndCmd RedirectToAbnormalLocOfAngleScan(TaskAndCmd taskAndCmd, long angleScanLoc, string remark)
    {
        if (taskAndCmd.Task.GroupNo.HasValue)
        {
            this.ClearGroupNo(taskAndCmd, $"任务{taskAndCmd.Task.TaskNo}在角度扫描位置{angleScanLoc}重定向到异常口");
        }

        WcsInCuringHelper.UpdateAngleTime(this.m_Db, taskAndCmd?.Task?.TrackId ?? 0);

        //this.BakAndDeleteTask(taskAndCmd.Task, angleScanLoc, remark);

        var abnormalPath = this.ChooseAbnormalPathOfAngleScan(angleScanLoc);

        return this.EditorTaskAndCmdToAbnormal(taskAndCmd, angleScanLoc, $"替换原任务{taskAndCmd.Task.TaskNo}。原因为：{remark}", abnormalPath);
    }

    private POWcsNetAbnormal ChooseAbnormalPathOfAngleScan(long angleScanLoc)
    {
        var abnormalPaths = PathHelper.GetAbnormalPathsOfAngleScanLoc(angleScanLoc);

        int? maxTaskCmdCount = null;
        POWcsNetAbnormal finalPath = null;

        foreach (var abnormalPath in abnormalPaths)
        {
            var emsPickLoc = abnormalPath.CacheLoc.Value;
            var count = this.m_Db.WcsTaskCmds.Count(item => item.TargetLoc == emsPickLoc || item.StartLoc == emsPickLoc);
            if (!maxTaskCmdCount.HasValue || count < maxTaskCmdCount.Value)
            {
                finalPath = abnormalPath;
                maxTaskCmdCount = count;
            }
        }

        if (finalPath == null)
        {
            throw new Exception($"未选择到开始位置为{angleScanLoc}的异常路线");
        }

        return finalPath;
    }

    public POWcsTaskCmd AddNewTaskCmdOfAngleScan(TaskAndCmd taskAndCmd, long angleScanLoc)
    {
        var task = taskAndCmd.Task;
        var taskCmd = taskAndCmd.TaskCmd;

        WcsInCuringHelper.UpdateAngleTime(this.m_Db, taskAndCmd?.Task?.TrackId ?? 0);

        if (task.EmsPickLoc.HasValue) //已经分配了角度扫描位置，直接添加指令
        {
            return this.AddTaskCmd(task, angleScanLoc, task.EmsPickLoc.Value, "已分配角度扫描位置，直接创建指令");
        }

        //未分配角度扫描位置
        var path = PathHelper.GetNormalPath(taskCmd.StartLoc.Value, task.TargetLoc.Value);
        var nextTaskCmd = this.m_Db.WcsTaskCmds.Where(t => t.TargetLoc == angleScanLoc &&
                                                            t.TaskId != taskCmd.TaskId &&
                                                            t.CmdStatus == (int)EnumTaskCmdStatus.Executed &&
                                                            t.CreateTime > task.CreateTime)
                                                .OrderBy(item => item.CreateTime)
                                                .FirstOrDefault();
        if (nextTaskCmd == null)
        {
            //单胎
            return this.AddTaskCmdForSingleTire(task, path);
        }
        else
        {
            var nextTask = this.m_Db.WcsTasks.Find(nextTaskCmd.TaskId);
            if (nextTask == null)
            {
                throw new Exception($"未找到Id为{nextTaskCmd.TaskId}的任务。指令Id为{nextTaskCmd.Id}");
            }

            var nextTaskTargetLoc = nextTask?.TargetLoc ?? 0;
            var currentTaskTargetLoc = task?.TargetLoc ?? 0;

            if(nextTaskTargetLoc == currentTaskTargetLoc)
            {
                //相同硫化机受台，先送单胎
                return this.AddTaskCmdForSingleTire(task, path);
            }

            //双胎
            return this.AddTaskCmdForDoubleTire(task, nextTask, path);
        }
    }

    /// <summary>
    /// 处理单胎的情况
    /// </summary>
    private POWcsTaskCmd AddTaskCmdForSingleTire(POWcsTask task, POWcsAsrsNetOutput path)
    {
        if (!task.CuringOrder.HasValue)
        {
            throw new Exception($"Id为{task.Id}的任务没有目标硫化机顺序号");
        }

        long emsPickLoc = 0;
        if (task.CuringOrder.Value > 6)
        {
            emsPickLoc = path.EmsPickLoc1.Value;
        }
        else
        {
            emsPickLoc = path.EmsPickLoc2.Value;
        }

        task.EmsPickLoc = emsPickLoc;
        XLogHelper.LogToDb(this.m_Db, $"设置单胎任务的角度扫描位。任务编号:{task.TaskNo}，角度扫描位：{emsPickLoc}", WcsLogMsgLevel.Debug, "设置单胎任务角度扫描位", task);

        return AddTaskCmdWithNewType(task, (int)EnumTaskType.Transportation, path.AngleScanLoc.Value, emsPickLoc, 0, "为单胎任务创建指令");
    }

    /// <summary>
    /// 处理双胎的情况
    /// </summary>
    private POWcsTaskCmd AddTaskCmdForDoubleTire(POWcsTask currentTask, POWcsTask nextTask, POWcsAsrsNetOutput path)
    {
        if (!currentTask.CuringOrder.HasValue)
        {
            throw new Exception($"Id为{currentTask.Id}的任务没有目标硫化机顺序号");
        }

        if (!nextTask.CuringOrder.HasValue)
        {
            throw new Exception($"Id为{nextTask.Id}的任务没有目标硫化机顺序号");
        }

        long currentTaskEmsPickLoc = 0;
        long nextTaskEmsPickLoc = 0;
        if (currentTask.CuringOrder.Value < nextTask.CuringOrder.Value)
        {
            currentTaskEmsPickLoc = path.EmsPickLoc2.Value;
            nextTaskEmsPickLoc = path.EmsPickLoc1.Value;
        }
        else
        {
            currentTaskEmsPickLoc = path.EmsPickLoc1.Value;
            nextTaskEmsPickLoc = path.EmsPickLoc2.Value;
        }

        int groupNo = CodeHelper.NextValue("InGroupNo").ToInt(0);
        currentTask.GroupNo = groupNo;
        currentTask.EmsPickLoc = currentTaskEmsPickLoc;

        nextTask.GroupNo = groupNo;
        nextTask.EmsPickLoc = nextTaskEmsPickLoc;

        XLogHelper.LogToDb(this.m_Db, $"设置双胎任务的取胎位。组号：{groupNo}，设置任务{currentTask.TaskNo}的取胎位为{currentTask.EmsPickLoc}", WcsLogMsgLevel.Debug, "胎胚分组", currentTask);
        XLogHelper.LogToDb(this.m_Db, $"设置双胎任务的取胎位。组号：{groupNo}，设置任务{nextTask.TaskNo}的取胎位为{nextTask.EmsPickLoc}", WcsLogMsgLevel.Debug, "胎胚分组", nextTask);

        return AddTaskCmdWithNewType(currentTask, (int)EnumTaskType.Transportation, path.AngleScanLoc.Value, currentTaskEmsPickLoc,0, "为双胎任务创建指令");
    }

    public void UpdateAngleExcuteTime(long inCuringId)
    {
        WcsInCuringHelper.UpdateAngleExcuteTime(this.m_Db, inCuringId);
    }

    #endregion

    #region EMS抓取位

    /// <summary>
    /// ems抓取位更新任务类型改为EMS，状态改为可执行
    /// </summary>
    public void UpdateTaskTypeAndStatusOfEmsPick(TaskAndCmd taskAndCmd)
    {
        if (!(taskAndCmd.Task.IsAbnormal ?? false))
        {
            taskAndCmd.Task.TaskType = (int)EnumTaskType.EMS;
            taskAndCmd.TaskCmd.CmdType = (int)EnumTaskType.EMS;
            taskAndCmd.TaskCmd.TaskType = (int)EnumTaskType.EMS;
        }
        taskAndCmd.Task.TaskStatus = (int)EnumTaskStatus.Executable;
        XLogHelper.LogToDb(this.m_Db, $"更新任务类型和任务状态。任务{taskAndCmd.Task.TaskNo}类型改为EMS，状态改为可执行", WcsLogMsgLevel.Debug, "更新任务类型和任务状态", taskAndCmd.Task);
    }

    public POWcsTaskCmd AddNewTaskCmdOfEmsPick(TaskAndCmd taskAndCmd, long emsPickLoc)
    {
        WcsInCuringHelper.UpdateEmsCreateTime(this.m_Db, taskAndCmd?.Task?.TrackId ?? 0);

        if (taskAndCmd.Task.IsAbnormal == true)
        {
            return this.AddAbnormalTaskCmd(taskAndCmd.Task, emsPickLoc, $"异常任务创建Ems指令");
        }
        else
        {
            var normalPath = PathHelper.GetNormalFromAnglePath(taskAndCmd.TaskCmd.StartLoc.Value, taskAndCmd.Task.TargetLoc.Value);
            return this.AddTaskCmd(taskAndCmd.Task, emsPickLoc, normalPath.TargetLoc.Value, "正常任务创建Ems指令");
        }
    }

    public void UpdateTaskBeanForSingleTask(EmsTaskBean taskBean, TaskAndCmd taskAndCmd, DitchConfig ditchConfig, int emsNo,int pickStation = 0)
    {
        var inCuringTire = this.m_Db.WcsInCuringTires.Find(taskAndCmd.Task.TrackId);
        if (inCuringTire == null)
        {
            taskBean.Error = $"未找到Id为{taskAndCmd.Task.TrackId}的入硫化信息";
            return;
        }

        if (taskAndCmd.Task.GroupNo.HasValue)
        {
            taskBean.Error = $"ems{emsNo}：胎号为{taskAndCmd.Task.SkuCode}的胎胚是双胎任务，等待另一任务创建。组号为{taskAndCmd.Task.GroupNo}，当前任务号为：{taskAndCmd.Task.TaskNo}";
            return;
        }

        WriteLog($"ems{emsNo}允许执行单胎任务。", true);
        if (emsNo == 1)
        {
            this.SetEmsTaskBeanOfTaskAInfo(taskBean, taskAndCmd, inCuringTire, pickStation != 0 ? pickStation : EmsConfig.PickStation1, ditchConfig);
            taskBean.CanExecute = true;
            taskBean.SingleDoubleFlag = 1;
        }
        else if (emsNo == 2)
        {
            this.SetEmsTaskBeanOfTaskBInfo(taskBean, taskAndCmd, inCuringTire, pickStation != 0 ? pickStation : EmsConfig.PickStation2, ditchConfig);
            taskBean.CanExecute = true;
            taskBean.SingleDoubleFlag = 1;
        }
    }

    public void UpdateTaskBeanForDoubleTask(EmsTaskBean taskBean, TaskAndCmd taskAndCmd1, TaskAndCmd taskAndCmd2, DitchConfig ditchConfig)
    {
        WriteLog($"ems2个任务允许同时执行", true);

        var inCuringinfo1 = this.m_Db.WcsInCuringTires.Find(taskAndCmd1.Task.TrackId);
        if (inCuringinfo1 == null)
        {
            taskBean.Error = $"未找到Id为{taskAndCmd1.Task.TrackId}的入硫化信息";
            return;
        }
        var inCuringinfo2 = this.m_Db.WcsInCuringTires.Find(taskAndCmd2.Task.TrackId);
        if (inCuringinfo2 == null)
        {
            taskBean.Error = $"未找到Id为{taskAndCmd2.Task.TrackId}的入硫化信息";
            return;
        }

        this.SetEmsTaskBeanOfTaskAInfo(taskBean, taskAndCmd1, inCuringinfo1, EmsConfig.PickStation1, ditchConfig);
        this.SetEmsTaskBeanOfTaskBInfo(taskBean, taskAndCmd2, inCuringinfo2, EmsConfig.PickStation2, ditchConfig);
        taskBean.CanExecute = true;
        taskBean.SingleDoubleFlag = 2;
    }

    private void SetEmsTaskBeanOfTaskAInfo(EmsTaskBean taskBean, TaskAndCmd taskAndCmd, POWcsInCuringTire inCuringInfo, int pickStation, DitchConfig ditchConfig)
    {
        var tireHeight = inCuringInfo.Height.GetValueOrDefault() == 0 ? ditchConfig.TireHeight : inCuringInfo.Height.GetValueOrDefault();
        taskBean.TaskANo = taskAndCmd.Task.TaskNo.Value;
        taskBean.TaskAPickStation = pickStation;
        taskBean.TaskAPickHeight = ditchConfig.EmsPickMaxHeight - tireHeight / 2;
        taskBean.TaskASize = this.CalculateSize(inCuringInfo.Size.Value);
        taskBean.TaskAPutStation = LocHelper.GetPlcDestination(taskAndCmd.TaskCmd.TargetLoc.Value);
        taskBean.TaskAPutHeight = ditchConfig.EmsPutMaxHeight - tireHeight / 2;
    }

    private void SetEmsTaskBeanOfTaskBInfo(EmsTaskBean taskBean, TaskAndCmd taskAndCmd, POWcsInCuringTire inCuringInfo, int pickStation, DitchConfig ditchConfig)
    {
        var tireHeight = inCuringInfo.Height.GetValueOrDefault() == 0 ? ditchConfig.TireHeight : inCuringInfo.Height.GetValueOrDefault();
        taskBean.TaskBNo = taskAndCmd.Task.TaskNo.Value;
        taskBean.TaskBPickStation = pickStation;
        taskBean.TaskBPickHeight = ditchConfig.EmsPickMaxHeight - tireHeight / 2;
        taskBean.TaskBSize = this.CalculateSize(inCuringInfo.Size.Value);
        taskBean.TaskBPutStation = LocHelper.GetPlcDestination(taskAndCmd.TaskCmd.TargetLoc.Value);
        taskBean.TaskBPutHeight = ditchConfig.EmsPutMaxHeight - tireHeight / 2;
    }

    private int CalculateSize(double size)
    {
        return (int)(size * 10);
    }

    public void UpdateEmsExcuteTime(long inCuringId)
    {
        WcsInCuringHelper.UpdateEmsExcuteTime(this.m_Db, inCuringId);
    }
    #endregion
}
